import json
import re
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, JsonResponse
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.users.utils import check_verify_email_token
from celery_tasks.email.tasks import send_email_active
from redis import Redis
from apps.users.models import User
from apps.users.utils import generate_verify_email_url
from logs import logger
from utils.views import LoginRequiredJSONMixin


class UsernameCountView(View):

    def get(self, request, username):
        # - 1 接收 用户名
        print(username)

        # 校验数据

        #   - 2 根据用户名查询数据库，查询数量有几个
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            print(e)
            return JsonResponse({"code": "15", "errmsg": "数据异常"})

        print("count=", count)
        #   - 3 返回json数据
        response = JsonResponse({"count": count, "code": "1", "errmsg": "OK"})

        return response


# 注册接口
class RegisterView(View):

    def post(self, request):
        # - 2.1 接收数据 获取到json数据
        body_byte = request.body
        # 把byte类型的json数据 转为字典
        data_dict = json.loads(body_byte)
        username = data_dict.get('username')
        password = data_dict.get('password')
        password2 = data_dict.get('password2')
        mobile = data_dict.get('mobile')
        sms_code = data_dict.get('sms_code')
        allow = data_dict.get('allow')

        #   - 2.2 验证数据 （数据不能为空   数据正则的验证）
        # all 里面传的列表的数据里 只要有一个是False 结果就是False
        if not all([username, password, password2, mobile, sms_code, allow]):
            return JsonResponse({'code': 400, 'errmsg': '数据上传错误'})

        # 正则
        # if not re.match(r'',username):
        #      return JsonResponse({'code': 400, 'errmsg': '数据格式错误'})
        # 两次密码是否一直
        # 是否同意的协议 allow

        #   - 2.3 生成用户对象 保存到数据库
        # user = User(username=username,password=password,mobile=mobile)
        # user.save()
        # User.objects.create(username=username,password=password,mobile=mobile)

        # -- 1从redis取短信验证码不要忘记decode

        redis: Redis = get_redis_connection('code')
        print(redis)
        sms_code_redis = redis.get('smscode_%s' % mobile)
        print(f'取到 - {sms_code_redis}')
        # -- 2如果没取到说明过期了 ，返回错误
        if not sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '验证码码码过期'})
        # -- 3和用户发来的对比
        sms_code_redis = sms_code_redis.decode()
        if sms_code != sms_code_redis:
            return JsonResponse({'code': 400, 'errmsg': '验证码输入错误'})

        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '注册失败'})
        # 把用户信息保存到session
        login(request, user)

        #   - 2.4 返回响应（json）
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response


# 登录接口
class LoginView(View):
    def post(self, request):
        # 1.接收参数
        dict = json.loads(request.body)
        username = dict.get('username')
        password = dict.get('password')
        remembered = dict.get('remembered')
        print('username', username)
        print('password', password)
        # 2.校验(整体 + 单个)
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})

        import re
        if re.match('^1[3-9]\d{9}$', username):
            # 手机号
            User.USERNAME_FIELD = 'mobile'
        else:
            # account 是用户名
            # 根据用户名从数据库获取 user 对象返回.
            User.USERNAME_FIELD = 'username'
        # 3.验证是否能够登录
        user = authenticate(username=username, password=password)
        print(user)
        # 判断是否为空,如果为空,返回
        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '用户名或者密码错误'})

        # 4.状态保持
        login(request, user)
        print(request)
        # 5.判断是否记住用户
        if remembered != True:
            # 7.如果没有记住: 关闭立刻失效
            request.session.set_expiry(0)
        else:
            # 6.如果记住:  设置为两周有效
            request.session.set_expiry(None)

        # 8.返回json
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 注册时用户名写入到cookie，有效期15天
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

        return response


# 退出登录
class LogoutView(View):
    """退出登录"""

    def delete(self, request):
        """实现退出登录逻辑"""
        # 清理session
        logout(request)
        # 退出登录，重定向到登录页
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 退出登录时清除cookie中的username
        response.delete_cookie('username')

        return response


# 个人信息
class UserInfoView(LoginRequiredMixin, View):
    def get(self, request):
        print(request.user.username, '---', request.user.mobile)

        info_data = {
            "username": request.user.username,
            "mobile": request.user.mobile,
            "email": request.user.email,
            "email_active": request.user.email_active
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'info_data': info_data})


# 添加邮箱
class EmailView(LoginRequiredMixin, View):
    def put(self, request):
        # 1. 获取json数据解码转为字典
        json_dict = json.loads(request.body)
        # 2. 从字典里拿到邮箱地址
        email = json_dict.get('email')
        print(email)

        # 3. 校验
        if not email:
            return JsonResponse({'code': 400, 'errmsg': '邮箱不存在'})

        # 4. 赋值email
        try:
            # 用户对象在request.user里
            request.user.email = email
            request.user.save()
        except Exception as e:
            print(e)
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': '添加邮箱失败'})

        # 发送链接后打开的地址
        verify_url = generate_verify_email_url(request.user)
        message = '<p>嘿 锤子 欢迎来到！</p>' \
                  '<p>感谢您使用米奇妙妙屋。</p>' \
                  '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                  '<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)

        send_email_active.delay(email, message)
        return JsonResponse({'code': 0, 'errmsg': '添加邮箱成功'})


# 激活邮箱
class EmailVerifyView(View):
    def put(self, request):
        # 1. 获取token
        token = request.GET.get('token')

        # 2. 对token解密 获取解密里的user_id
        user_id = check_verify_email_token(token)

        # 3. 若获取不到 则说明过期
        if not user_id:
            return JsonResponse({'code': 400, 'errmsg': '激活邮件已经过期'})

        # 4. 根据user_id去数据库查询
        try:
            user = User.objects.get(id=user_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 405, 'errmsg': '当前用户不存在'})

        # 5. 把查到user对象的email_active字段改为 true
        user.email_active = True
        user.save()
        # try:
        #     user.save()  # 保存
        # except Exception as e:
        #     print(e)
        #     return JsonResponse({'code': 444, 'errmsg': '保存数据失败,网络连接出现问题'})
        return JsonResponse({'code': 0, 'errmsg': '激活成功'})


# 保存浏览记录
class UserBrowseHistory(LoginRequiredJSONMixin, View):
    def post(self, request):
        # 获取当前登录的用户
        user = request.user

        # 接收提取参数
        data_dict = json.loads(request.body)
        sku_id = data_dict.get('sku_id')

        # ｉｄ校验
        if not sku_id:
            return JsonResponse({'code': 400, 'errmsg': 'ｓｋｕ不存在'})

        # 查询校验
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        # 保存浏览记录
        redis_conn: Redis = get_redis_connection("history")
        # 通过管道让三个任务同时传达
        pl = redis_conn.pipeline()
        # １．去重
        pl.lrem('history_%s' % user.id, 0 , sku_id)
        # ２．存储
        pl.lpush('history_%s' % user.id, sku_id)
        # ３．截取５个
        pl.ltrim('history_%s' % user.id, 0, 4)
        # 执行管道命令
        pl.execute()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})

    # 获取用户浏览记录
    def get(self, request):
        user = request.user
        try:
            redis_conn: Redis = get_redis_connection("history")
            sku_ids = redis_conn.lrange('history_%s' % user.id, 0, -1)
            skus = []
            for sku_id in sku_ids:
                sku = SKU.objects.get(id=sku_id)
                sku.append({
                    'id': sku.id,
                    'name': sku.name,
                    'default_image_url': sku.default_image.url,
                    'price': sku.price
                })
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': 'data error'})

        return JsonResponse({'code': 0, 'errmsg': 'OK', 'skus': skus})


